/*
 *
 *  *    Copyright © OpenAtom Foundation.
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *         http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */

package com.inspur.edp.commonmodel.engine.api.data;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IValuesContainer;
import com.inspur.edp.cef.spi.entity.IAuthFieldValue;
import com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateSerUtil;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;
import com.inspur.edp.cef.spi.jsonser.util.SerializerUtil;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class AssoInfoJsonSerializer extends JsonSerializer<AssociationInfo> {

    private static ObjectMapper defaultMapper = new ObjectMapper();

    @Override
    public void serialize(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException {
        if (associationInfo == null) {
            jsonGenerator.writeNull();
        } else {
            jsonGenerator.writeStartObject();
            if (associationInfo.getAssociation() == null) {
                serializeCore(associationInfo, jsonGenerator, serializerProvider);
            } else {
                serializeCoreWithAsso(associationInfo, jsonGenerator, serializerProvider);
            }
            jsonGenerator.writeEndObject();
        }
    }

    private void serializeCore(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
                               SerializerProvider serializerProvider) throws IOException {
        for (Map.Entry<String, Object> pair : associationInfo.getValues().entrySet()) {
            jsonGenerator.writeFieldName(StringUtils.toCamelCase(pair.getKey()));
            Object value = pair.getValue();
            if (value instanceof Date) {
                if (value == null) {
                    jsonGenerator.writeNull();
                } else {
                    jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDateTime((Date) value));
                }
            } else if (value instanceof ICefData) {
                jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
            } else {
                serializerProvider.defaultSerializeValue(pair.getValue(), jsonGenerator);
            }
        }
    }

    private void serializeCoreWithAsso(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
                                       SerializerProvider serializerProvider) throws IOException {
        List<GspAssociation> associations = associationInfo.getAssociations();
        GspFieldCollection fieldCollection;
        if (associations != null && !associations.isEmpty()) {
            if (associations.get(0).getBelongElement() != null) {
                jsonGenerator
                        .writeFieldName(StringUtils.toCamelCase(associations.get(0).getBelongElement().getLabelID()));
                Object value = associationInfo.getValue(associations.get(0).getBelongElement().getLabelID());
                serializerProvider.defaultSerializeValue(value, jsonGenerator);
            }
            for (GspAssociation association : associations) {
                fieldCollection = association.getRefElementCollection();
                if (!fieldCollection.isEmpty()) {
                    for (IGspCommonField field : fieldCollection) {
                        if (association.getBelongElement() != null && field.getLabelID()
                                .equalsIgnoreCase(association.getBelongElement().getLabelID())) {
                            continue;
                        }
                        jsonGenerator.writeFieldName(StringUtils.toCamelCase(field.getLabelID()));
                        Object value = associationInfo.getValue(field.getLabelID());
                        if (value == null) {
                            jsonGenerator.writeNull();
                        } else if (value instanceof Date) {
                            switch (field.getMDataType()) {
                                case DateTime:
                                    jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDateTime((Date) value));
                                    break;
                                case Date:
                                    jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDate((Date) value));
                                    break;
                                default:
                                    serializerProvider.defaultSerializeValue(value, jsonGenerator);
                                    break;
                            }
                        } else if (value instanceof ICefData) {
                            if (field.getObjectType() == GspElementObjectType.Association) {
                                boolean isKeepAssoForExp = false;
                                if (field.getHasAssociation()) {
                                    isKeepAssoForExp = field.getChildAssociations().get(0).isKeepAssoPropertyForExpression();
                                }
                                //如果带出字段兼容关联,确保只有表达式序列化的，才增加兼容关联的属性判断
                                if ("1".equals(SerializerUtil.isKeepAssoPropertyForExpression().get()) && isKeepAssoForExp && (value instanceof IAuthFieldValue)) {
                                    String assValue = ((IAuthFieldValue) value).getValue() == null ? "" : ((IAuthFieldValue) value).getValue();
                                    jsonGenerator.writeString(assValue);
                                    jsonGenerator.writeFieldName(StringUtils.toCamelCase(field.getLabelID()) + "___AssoExt");
                                    jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
                                } else {
                                    jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
                                }
                            } else {
                                jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
                            }
                        } else {
                            serializerProvider.defaultSerializeValue(value, jsonGenerator);
                        }
                    }
                }
            }
        }

    }
}
